package com.qumitech.visualnovel.service.voiceRoom.impl;

import com.alibaba.fastjson.JSONObject;
import com.qumitech.visualnovel.component.exception.BusinessException;
import com.qumitech.visualnovel.component.util.DateUtil;
import com.qumitech.visualnovel.component.util.HttpInvokeUtil;
import com.qumitech.visualnovel.component.util.bash.FileUtils;
import com.qumitech.visualnovel.component.util.bash.PythonUtils;
import com.qumitech.visualnovel.component.config.Config;
import com.qumitech.visualnovel.model.common.BaseRsp;
import com.qumitech.visualnovel.model.common.ResultEnum;
import com.qumitech.visualnovel.controller.vo.voiceRoom.LiveConversionQueryDTO;
import com.qumitech.visualnovel.controller.vo.voiceRoom.VoiceRoomAnchorVO;
import com.qumitech.visualnovel.model.dao.console.UserInfo;
import com.qumitech.visualnovel.model.common.UrlConstant;
import com.qumitech.visualnovel.pubdef.dto.voiceroom.*;
import com.qumitech.visualnovel.service.exception.ExceptionService;
import com.qumitech.visualnovel.service.voiceRoom.VoiceRoomAnchorService;
import com.qumitech.visualnovel.datasource.console.ActivityDataMapper;
import com.google.common.collect.ImmutableMap;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.File;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @Author :  ZhChNing
 * @Descriptiom :
 * @Date Created in 2019/4/17 16:22
 */
@Service
public class VoiceRoomAnchorServiceImpl implements VoiceRoomAnchorService {

    private final String anchorURL = "/voiceroom/anchor";
    private final String anchorAdminURL = "/admin/voiceroom/anchor";
    private final String VOICE_ROOM_CONSOLE_URL = "/voiceroom/console";
    private final String VOICE_ROOM_SHORT_ID_URL = "/short_id";
    private final String VOICE_ROOM_WHITE_CONFIG_URL = "/white/config";
    private final String REBATE_TYPE_OPTION_URL = "/voiceroom/console/rebate_type";

    @Autowired
    private ExceptionService exceptionService;
    @Autowired
    private DateUtil dateUtil;
    @Autowired
    private ActivityDataMapper activityDataMapper;

    @Override
    public void updateAnchor(VoiceRoomAnchorVO anchorVO) {
        String url = UrlConstant.SERVER_URL + anchorURL + "/" + anchorVO.getAnchorId();
        String req = JSONObject.toJSONString(anchorVO);
        String body = HttpInvokeUtil.httpPutJson(url, req, UrlConstant.DefaultEncode, null);
        BaseRsp rsp = JSONObject.parseObject(body, BaseRsp.class);
        if (rsp == null || rsp.getStatus() != ResultEnum.SUCCESS.getState()) {
            throw new BusinessException(ResultEnum.FAILURE);
        }

    }

    @Override
    public Map<String, Object> listVoiceRoomAnchorVO(Long uid,Byte type,Byte status,Integer offset,Integer limit) {
        String url = UrlConstant.SERVER_URL + anchorAdminURL;
        Map<String, String> paramMap = new HashMap<>();

        if (offset != null) {
            paramMap.put("offset", offset.toString());
        }
        if (limit != null) {
            paramMap.put("limit", limit.toString());
        }
        if (type != null) {
            paramMap.put("type", type.toString());
        }
        if (status != null) {
            paramMap.put("status", status.toString());
        }
        if (uid != null) {
            paramMap.put("uid", uid.toString());
        }


        String body = HttpInvokeUtil.httpGet(url, paramMap, null);
        BaseRsp rsp = JSONObject.parseObject(body, BaseRsp.class);
        if (rsp == null || rsp.getStatus() != ResultEnum.SUCCESS.getState()
                || rsp.getData() == null) {
            throw new BusinessException(ResultEnum.FAILURE);
        }
        Map<String, Object> rspMap = (Map<String, Object>) rsp.getData();
        return rspMap;
    }

    @Override
    public Map<String, Object> listExistShortIdVoiceRoom(Map<String, String> paramMap) {
        String url = UrlConstant.SERVER_URL + VOICE_ROOM_CONSOLE_URL + VOICE_ROOM_SHORT_ID_URL;
        String body = HttpInvokeUtil.httpGet(url, paramMap, null);
        BaseRsp rsp = JSONObject.parseObject(body, BaseRsp.class);
        exceptionService.getFailureResultEnum(rsp);
        Map<String, Object> rspMap = (Map<String, Object>) rsp.getData();
        return rspMap;
    }

    @Override
    public void addVoiceRoomShortId(VoiceRoomShortIdAdminDTO shortIdAdminDTO) {
        String url = UrlConstant.SERVER_URL + VOICE_ROOM_CONSOLE_URL + VOICE_ROOM_SHORT_ID_URL;
        String req = JSONObject.toJSONString(shortIdAdminDTO);
        String body = HttpInvokeUtil.httpPostJson(url, req, UrlConstant.DefaultEncode, null);
        BaseRsp rsp = JSONObject.parseObject(body, BaseRsp.class);
        exceptionService.getFailureResultEnum(rsp);
    }

    @Override
    public void deleteVoiceRoomShortIdByUid(Long uid) {
        String url = UrlConstant.SERVER_URL + VOICE_ROOM_CONSOLE_URL + VOICE_ROOM_SHORT_ID_URL + "/" + uid;
        String body = HttpInvokeUtil.httpDelete(url, null);
        BaseRsp rsp = JSONObject.parseObject(body, BaseRsp.class);
        exceptionService.getFailureResultEnum(rsp);
    }

    @Override
    public BaseRsp listVoiceRoomWhiteCfgAdminQueryDTO(VoiceRoomWhiteCfgAdminQueryDTO queryDTO) {

        Map<String, String> paramMap = new HashMap<>();

        if (queryDTO.getOffset() != null) {
            paramMap.put("offset", queryDTO.getOffset().toString());
        }
        if (queryDTO.getLimit() != null) {
            paramMap.put("limit", queryDTO.getLimit() .toString());
        }
        if (queryDTO.getPresentId() != null) {
            paramMap.put("present_id", queryDTO.getPresentId().toString());
        }
        if (queryDTO.getAnchorId() != null) {
            paramMap.put("anchor_id", queryDTO.getAnchorId().toString());
        }

        String url = UrlConstant.SERVER_URL + VOICE_ROOM_CONSOLE_URL+VOICE_ROOM_WHITE_CONFIG_URL ;
        String body = HttpInvokeUtil.httpGet(url, paramMap, null);
        return JSONObject.parseObject(body, BaseRsp.class);
    }

    @Override
    public BaseRsp addVoiceRoomWhiteCfg(VoiceRoomWhiteCfgDTO voiceRoomWhiteCfgDTO) {
        String url = UrlConstant.SERVER_URL + VOICE_ROOM_CONSOLE_URL+VOICE_ROOM_WHITE_CONFIG_URL ;
        String req = JSONObject.toJSONString(voiceRoomWhiteCfgDTO);
        String body = HttpInvokeUtil.httpPostJson(url, req, UrlConstant.DefaultEncode, null);
        return JSONObject.parseObject(body, BaseRsp.class);
    }

    @Override
    public BaseRsp rmVoiceRoomWhiteCfg(String roomId) {
        String url = UrlConstant.SERVER_URL + VOICE_ROOM_CONSOLE_URL+VOICE_ROOM_WHITE_CONFIG_URL+ "/"+roomId;
        String body = HttpInvokeUtil.httpDelete(url, new HashMap<>());
        return JSONObject.parseObject(body, BaseRsp.class);
    }

    private String fileRoot = Config.getProperty("app.generatedFileRoot");
    @Override
    public BaseRsp getLiveConversionStatistics(LiveConversionQueryDTO queryDTO) {
        if (queryDTO.getStartTime() == null ||
                queryDTO.getEndTime() == null ||
                queryDTO.getStreamerId() == null ||
                queryDTO.getOffset() == null ||
                queryDTO.getLimit() == null ||
                queryDTO.getPhase() == null) {
            throw new BusinessException(ResultEnum.PARA_ERR);
        }
        // 计算文件名.
        // 开始进入时间
        Date startDate = new Date(dateUtil.DateToTimestamp(queryDTO.getStartTime()) * 1000);
        // 结束进入时间
        Date endDate = new Date(dateUtil.DateToTimestamp(queryDTO.getEndTime()) * 1000);
        // 周期截止时间: 使用的时候只需要用日期级别的数据，直接+就完事。
        Date toDate = Date.from(endDate.toInstant().plusSeconds((queryDTO.getPhase() + 1) * 24 * 60 * 60L));
//        Calendar.getInstance().set(toDate.getYear(), toDate.getMonth(), toDate.getDay());
        toDate = new Date(dateUtil.dateToStamp(dateUtil.dateToStr(toDate),"yyyy-MM-dd"));

        Date curDate = new Date();

        if (curDate.after(toDate)) {
            curDate = toDate;
        }

        String datetimeFormat = "yyyy-MM-dd-HH-mm-ss";
        String fileName = String.format("account_direct_seeding_%s_%s_%s_%s_%s_%s.json",
                queryDTO.getStreamerId(),
                dateUtil.GetFormatDate(startDate, datetimeFormat),
                dateUtil.GetFormatDate(endDate, datetimeFormat),
                dateUtil.dateToStr(startDate),
                dateUtil.dateToStr(toDate),
                dateUtil.GetFormatDate(curDate, "yyyy-MM-dd-HH-mm")
        );
        final File destFile = new File(fileRoot, fileName);
        final File lockFile = new File(fileRoot, fileName + ".lock");
        if (destFile.exists()) {
            if (queryDTO.getExport() != null && queryDTO.getExport() == 1) {
                String exportFileName = fileName.replace("json", "xlsx");
                return new BaseRsp(ResultEnum.SUCCESS, "/excel_export/" + exportFileName);
            } else {
                // 进入读取流程
                int lineCount = FileUtils.fileLength(destFile.getPath());
                List<String> result = FileUtils.readOffsetLimit(destFile.getPath(), queryDTO.getOffset(), queryDTO.getLimit());
                List<JSONObject> jsonResult = result.stream().map(JSONObject::parseObject).collect(Collectors.toList());
                return new BaseRsp(ResultEnum.SUCCESS, ImmutableMap.of("list", jsonResult, "count", lineCount));

            }
        } else if (lockFile.exists()) {
            return new BaseRsp(ResultEnum.SUCCESS.getState(), "数据正在计算, 请过10秒左右再点一下查询...期间请勿修改查询参数", null);
        } else {
            String datetimeFormatNoBlank = "yyyy-MM-ddHH:mm:ss";
            PythonUtils.execute("jobs/export_account_direct_seeding.py",
                    queryDTO.getStreamerId(),
                    dateUtil.GetFormatDate(startDate, datetimeFormatNoBlank), // 开始进入房间时间
                    dateUtil.GetFormatDate(endDate, datetimeFormatNoBlank),    // 结束进入房间时间
                    dateUtil.GetFormatDate(startDate, datetimeFormatNoBlank), // 开始注册时间
                    dateUtil.GetFormatDate(endDate, datetimeFormatNoBlank), // 结束注册时间
                    dateUtil.dateToStr(startDate), // 开始统计数据日期
                    dateUtil.dateToStr(toDate), // 结束统计数据日期
                    "1" // 1: 统计进入房间的用户  0: 统计送礼用户
                    );
            return new BaseRsp(ResultEnum.SUCCESS.getState(), "数据正在计算，请过10秒左右再点一下查询...期间请勿修改查询参数", null);
        }
    }

    @Override
    public List<ActivityConfigDTO> getActivitiesList(String activityName, Long streamerId, String startTime, String endTime, Integer offset, Integer limit, String orderBy, String orderType) {
        return activityDataMapper.getActivitiesList(activityName, streamerId, startTime, endTime, offset, limit, orderBy, orderType);
    }

    @Override
    public int getActivitiesListCount(String activityName, Long streamerId, String startTime, String endTime) {
        return activityDataMapper.getActivitiesListCount(activityName, streamerId, startTime, endTime);
    }

    public String getOperatorName() {
        Subject subject = SecurityUtils.getSubject();
        UserInfo activeUser = (UserInfo) subject.getPrincipal();
        return activeUser.getUsername();
    }

    @Override
    public int updateActivity(List<ActivityConfigDTO> activityDTO) {
        boolean check = true;
        String operator = getOperatorName();
        for (ActivityConfigDTO record: activityDTO) {
            record.setOperator(operator);
            if (record.getId() == null){
                if (record.getActivityName() != null && record.getStreamerId() != null) {
                    int length = activityDataMapper.getActivitiesListCount(
                            record.getActivityName(), null, null, null);
                    if (length != 0 && check) {
                        return 2; } else {
                        check = false;
                        activityDataMapper.addActivity(record);}
                } else {
                    return 0;
                }
            } else {
                record.setUpdateTime(dateUtil.getCurrentTime());
                activityDataMapper.updateActivity(record);
            }
        }
        return 1;
    }

    @Override
    public void deleteActivity(Map<String, String> map) {
        String activityName = map.get("activityName");
        activityDataMapper.deleteActivity(activityName);
    }

    @Override
    public List<ActivityDataDTO> getActivityUsersList(String activityName, Long streamId, Integer offset, Integer limit, String orderBy, String orderType) {
        return activityDataMapper.getActivityUsersList(activityName, streamId, offset, limit, orderBy, orderType);
    }

    @Override
    public List<HashMap<String,Object>> getActivityUsersListCount(String activityName, Long streamId) {
        return activityDataMapper.getActivityUsersListCount(activityName, streamId);
    }

    @Override
    public List<ActivityRemainDataDTO> getActivityRemainList(String activityName, Long streamId, Integer offset, Integer limit, String orderBy, String orderType) {
        return activityDataMapper.getActivityRemainList(activityName, streamId, offset, limit, orderBy, orderType);
    }

    @Override
    public BaseRsp getRebateTypeOption() {
        String url = UrlConstant.SERVER_URL + REBATE_TYPE_OPTION_URL;
        String body = HttpInvokeUtil.httpGet(url, new HashMap<>());
        return JSONObject.parseObject(body, BaseRsp.class);
    }

}
